package com.lili.collection.core.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.lili.collection.core.context.BatchRecordContext;
import com.lili.collection.core.domain.CollectCommonConfig;
import com.lili.collection.core.domain.FetchDataInfo;
import com.lili.collection.core.enums.DataFormat;
import com.lili.collection.core.enums.FieldType;
import com.lili.collection.core.enums.TargetStoreType;
import com.lili.collection.core.fields.Field;
import com.lili.collection.core.handler.IDataHandler;
import com.lili.collection.core.handler.ISendMsg;
import com.lili.collection.core.processor.JSONFlatProcessor;
import com.lili.collection.core.processor.JSONUnFlatProcessor;
import com.lili.collection.core.record.impl.CommonRecord;
import com.lili.collection.core.runner.result.RecordInfo;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONPath;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 *描述: 处理数据工具集
 *@date: 2023/10/27  16:57
 *@author: lili
 */
@Slf4j
public class HandlerUtil {

    /**
     * 解析响应的数据
     * @param config
     * @param response
     * @param recordContext
     * @return
     */
    public static RecordInfo getRecordInfo(CollectCommonConfig config, String response, BatchRecordContext recordContext) {
        IDataHandler dataHandler = config.getDataHandler();
        if(dataHandler!=null){
            response=dataHandler.onHandler(response);
        }
        RecordInfo record = new RecordInfo();
        if(config.getDataFormat()== DataFormat.ORIGIN){
            HandlerUtil.validData(response,config.getRespDataType());
            if(config.getStoreType() == TargetStoreType.DB){
                parseResponseData(config, response, recordContext, record);
            }else {
                record.incrementSuccessCount();
                record.incrementTotalCount();
                recordContext.setRecord(new CommonRecord(Field.create(Field.Type.OBJECT, response)));
            }
        }else if(config.getDataFormat()== DataFormat.ORIGIN_CONVERT){
            String convertJson = JsonPathAnalysisUtil.getConvertJson(response, config.getAliasMap(), config.getBasePath());
            record.incrementSuccessCount();
            record.incrementTotalCount();
            recordContext.setRecord(new CommonRecord(Field.create(Field.Type.OBJECT, convertJson)));
        } else {
            JSONFlatProcessor processor = new JSONFlatProcessor();
            processor.setConfigMap(config.getAliasMap());
            processor.process(response);
            processor.setFetchInfo(new FetchDataInfo(config,record));
            FetchDataInfo fetchDataInfo = processor.generateFlatData();
            if(fetchDataInfo==null){
                throw new IllegalArgumentException("该配置不能解析响应数据，请核实配置或响应数据："+StrCutUtil.getCutLengthData(response));
            }
            List<Map<String, Field>> dataList = fetchDataInfo.getDataList();
            if (CollectionUtil.isEmpty(dataList)) {
                return null;
            }
            for (Map<String, Field> rowData : dataList) {
                recordContext.setRecord(new CommonRecord(Field.create(rowData)));
            }
        }
        return record;
    }

    /**
     * 解析为数据库存储格式类型
     * @param config 公共配置
     * @param response 响应数据
     * @param recordContext  接收上下文
     * @param record 采集上下文
     */
    private static void parseResponseData(CollectCommonConfig config, String response, BatchRecordContext recordContext,RecordInfo record) {
        String key = config.getAliasMap().values().stream().findFirst().get();
        if(config.getRespDataType().isArray()){
            for (Object obj : JSON.parseArray(response)) {
                Map<String, Field> oneRowDataMap=new LinkedHashMap<>();
                oneRowDataMap.put(key,Field.create(Field.Type.OBJECT, DateConvertUtil.dateTypeHandle(obj)));
                recordContext.setRecord(new CommonRecord(Field.create(oneRowDataMap)));
                record.incrementSuccessCount();
                record.incrementTotalCount();
            }
        } else {
            Map<String, Field> oneRowDataMap=new LinkedHashMap<>();
            oneRowDataMap.put(key,Field.create(Field.Type.OBJECT, DateConvertUtil.dateTypeHandle(response)));
            recordContext.setRecord(new CommonRecord(Field.create(oneRowDataMap)));
            record.incrementSuccessCount();
            record.incrementTotalCount();
        }
    }

    /**
     * 发送处理了的数据
     * @param config 配置
     * @param jsonData json格式数据
     * @param msg 发送的具体实现
     */
    public static boolean sendProcessedData(RecordInfo recordInfo,CollectCommonConfig config, String jsonData, ISendMsg msg) throws Exception {
        DataFormat dataFormat = config.getDataFormat();
        if(dataFormat== DataFormat.PACKAGE){
            JSONUnFlatProcessor processor=new JSONUnFlatProcessor();
            processor.parseArrayData(jsonData);
            return msg.sendProducer(processor.toString());
        }else if(dataFormat == DataFormat.LIST){
            return msg.sendProducer(jsonData);
        }else if(dataFormat == DataFormat.OBJECT){
            JSONArray array = JSON.parseArray(jsonData);
            for (Object obj : array) {
                if(obj instanceof JSONObject){
                    JSONUnFlatProcessor processor=new JSONUnFlatProcessor();
                    processor.parseSingleMap((JSONObject)obj);
                    if(!msg.sendProducer(processor.toString())){
                        throw new IllegalArgumentException("消息发送异常！");
                    }
                    recordInfo.incrementSuccessCount();
                }
            }
            return true;
        } else {
            throw new IllegalArgumentException("当前【"+dataFormat+"】格式不支持发送！");
        }
    }

    /**
     * 验证响应数据类型
     * @param response
     * @param respDataType
     * @return
     */
    public static void validData(String response, FieldType respDataType){
        if(respDataType!=null){
            //基本数据类型
            if(respDataType.isBaseType()){
                respDataType.convert(response);
            }else if(respDataType.isArray()){
                JSON.parseArray(response);
            }else if(respDataType.isObject()){
                JSON.parseObject(response);
            }
        }else {
            throw new IllegalArgumentException("响应类型参数不能为空！");
        }
    }

    /**
     * 根据原始数据获取主键key
     * @param primaryKeySet key字段
     * @param sendData 数据
     * @return
     */
    public static String getPrimaryKeyByData(Set<String> primaryKeySet,String sendData){
        if(CollectionUtils.isEmpty(primaryKeySet) || StringUtils.isBlank(sendData)){
            return null;
        }
        try {
            Object parseData = JSON.parse(sendData);
            if(!(parseData instanceof JSONObject)){
                return null;
            }
            JSONObject parseObj=(JSONObject)parseData;
            StringBuilder keyBuilder=new StringBuilder();
            for (String primaryKey : primaryKeySet) {
                Object value = parseObj.eval(JSONPath.of("$." + primaryKey));
                if(ObjectUtil.isEmpty(value)){
                    return null;
                }
                if((value instanceof JSONObject) || (value instanceof JSONArray)){
                    return null;
                }
                keyBuilder.append(value.toString());
            }
            return keyBuilder.length()>0 ?  keyBuilder.toString() : null;
        } catch (Exception e) {
            log.error("获取主键失败！",e);
            return null;
        }
    }
}
